package com.nekonomics
package config

import com.zaxxer.hikari.HikariConfig
import doobie.hikari.HikariTransactor
import doobie.*
import doobie.implicits.*
import doobie.util.log.LogEvent
import zio.*
import zio.interop.catz.*

final case class DBConfig(
  jdbcUrl: String,
  username: String,
  password: String,
  driver: String,
  maximumPoolSize: Int = 32
) {
  def toHikariConfig: HikariConfig = {
    val config = HikariConfig()
    config.setUsername(username)
    config.setPassword(password)
    config.setDriverClassName(driver)
    config.setMaximumPoolSize(maximumPoolSize)
    config.setJdbcUrl(jdbcUrl)
    config
  }
}

object DBConfig {
  val live: ZLayer[Any, Nothing, DBConfig] = ZLayer.fromZIO {
    ZIO.succeed(DBConfig(
      jdbcUrl = "jdbc:postgresql://localhost:5432/nekonomics",
      username = "postgres",
      password = "DB123456",
      driver = "org.postgresql.Driver"
    ))
  }
}


object DBTransactor {

  private val printSqlLogHandler: LogHandler[Task] = (logEvent: LogEvent) => ZIO.logInfo(s"【query】 ${logEvent.sql}")

  val live: ZLayer[DBConfig, Throwable, HikariTransactor[Task]] = ZLayer.scoped(mkTransactor)

  private def mkTransactor: ZIO[Any & Scope & DBConfig, Throwable, HikariTransactor[Task]] =
    for {
      config <- ZIO.service[DBConfig]
      xa <- HikariTransactor.fromHikariConfig[Task](config.toHikariConfig).toScopedZIO
    } yield xa.withLogHandler(printSqlLogHandler)

}


